#include "kx/X11Window.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"

using namespace Kx;

Kx::X11Window::X11Window(Display *display, unsigned long windowId)
    : mWindowId(windowId), m_Display(display)
{
    mWindowName = getWindowName();
    mWindowTitle = getWindowTitle();
}

bool Kx::X11Window::SaveCurrentImage(const std::string &outPath)
{
    XWindowAttributes attr;
    XGetWindowAttributes(m_Display, mWindowId, &attr);

    XImage *img = XGetImage(m_Display, mWindowId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
    if (!img)
    {
        std::cerr << "Failed to get image" << std::endl;
        return false;
    }

    // 创建图像缓冲区
    unsigned char *buffer = new unsigned char[attr.width * attr.height * 4];
    if (!buffer)
    {
        std::cerr << "Failed to allocate memory for image buffer" << std::endl;
        XDestroyImage(img);
        return false;
    }

    // 将像素数据从 XImage 转换为 RGBA 格式
    for (int y = 0; y < attr.height; ++y)
    {
        for (int x = 0; x < attr.width; ++x)
        {
            unsigned long pixel = XGetPixel(img, x, y);
            int offset = (y * attr.width + x) * 4;
            buffer[offset + 0] = (pixel & img->red_mask) >> 16;
            buffer[offset + 1] = (pixel & img->green_mask) >> 8;
            buffer[offset + 2] = pixel & img->blue_mask;
            buffer[offset + 3] = 255; // Alpha channel
        }
    }

    // 保存图像数据到文件
    stbi_write_png(outPath.c_str(), attr.width, attr.height, 4, buffer, attr.width * 4);

    // 释放内存
    delete[] buffer;
    XDestroyImage(img);

    return true;
}

std::string Kx::X11Window::getWindowName()
{
    char *window_name;
    XFetchName(m_Display, mWindowId, &window_name);
    std::string name = window_name ? std::string(window_name) : "";
    XFree(window_name);
    return name;
}

std::string Kx::X11Window::getWindowTitle()
{
    char *windowTitle = nullptr;
    Atom actual_type;
    int actual_format;
    unsigned long nitems, bytes_after;
    unsigned char *prop;
    if (XGetWindowProperty(m_Display, mWindowId, XInternAtom(m_Display, "_NET_WM_NAME", False), 0, (~0L), False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success && prop)
    {
        windowTitle = (char *)prop;
    }
    std::string title = windowTitle ? std::string(windowTitle) : "";

    if (windowTitle)
    {
        XFree(windowTitle);
    }
    return title;
};
